#pragma once
#include <Rz/Object.h>
#include <Rz/IEquatable.h>
#include <Rz/IHumanReadable.h>
#include <Rz/Collections/InitializerList.h>

namespace Rz { namespace Graphics { namespace Math {

class Vector2 :
	public Object,
	public IEquatable<Vector2>,
	public IHumanReadable
{
	public:
		RZ_RTTI(Rz::Graphics, Vector2);
		RZ_RTTI_IMPLEMENTS(Object, IEquatable<Vector2>, IHumanReadable);
		RZ_RTTI_END;

		union
		{
			struct { f32 X, Y; };
			struct { f32 Cell[2]; };
		};

		Vector2();
		Vector2(std::initializer_list<f32> v);
		Vector2(f32 x, f32 y);
		Vector2(const f32* ptr);
		Vector2(const Vector2& vec);

		void Set(f32 x, f32 y);
		f32 Length() const;
		void Normalize();
		Vector2 Normalized() const;

		static f32 Dot(const Vector2& u, const Vector2& v);
		static f32 Distance(const Vector2& u, const Vector2& v);

		f32 operator [] (s32 index) const;
		f32& operator [] (s32 index);

		Vector2 operator + (const Vector2& vec) const;
		Vector2 operator - (const Vector2& vec) const;
		Vector2 operator * (const Vector2& vec) const;
		Vector2 operator / (const Vector2& vec) const;
		Vector2 operator + (f32 v) const;
		Vector2 operator - (f32 v) const;
		Vector2 operator * (f32 v) const;
		Vector2 operator / (f32 v) const;


		Vector2& operator += (const Vector2& v);
		Vector2& operator -= (const Vector2& v);
		Vector2& operator *= (const Vector2& v);
		Vector2& operator /= (const Vector2& v);
		Vector2& operator += (f32 v);
		Vector2& operator -= (f32 v);
		Vector2& operator *= (f32 v);
		Vector2& operator /= (f32 v);

		Vector2 operator - () const;

		friend Vector2 operator + (f32 v, const Vector2& u);
		friend Vector2 operator - (f32 v, const Vector2& u);
		friend Vector2 operator * (f32 v, const Vector2& u);
		friend Vector2 operator / (f32 v, const Vector2& u);

		// IHumanReadable
		String ToString() const override;

		// IEquatable
		bool Equals(const Vector2& r) const override;

		bool operator == (const Vector2& r) const override;
		bool operator != (const Vector2& r) const override;

		static const Vector2 Zero;
		static const Vector2 One;
		static const Vector2 NormalX;
		static const Vector2 NormalY;
};

} } }
